package xcmg.device.service.purchase;

import com.github.pagehelper.PageInfo;
import yb.ecp.fast.infra.util.PageHelperPlus;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xcmg.device.dao.entity.purchase.PurchasePlanDO;
import xcmg.device.dao.entity.sale.SaleIntentionDO;
import xcmg.device.dao.entity.sale.SaleIntentionDetailDO;
import xcmg.device.dao.mapper.PurchasePlanMapper;
import xcmg.device.dao.mapper.PurchaseRequestDetailMapper;
import xcmg.device.dao.mapper.SaleIntentionDetailMapper;
import xcmg.device.dao.mapper.SaleIntentionMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInventoryMapper;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ExportUtil;
import xcmg.device.service.vo.purchase.PurchasePlanVO;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class PurchasePlanService {

    @Autowired
    private SaleIntentionMapper saleIntentionMapper;

    @Autowired
    private SaleIntentionDetailMapper saleIntentionDetailMapper;

    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;

    @Autowired
    private PurchaseRequestDetailMapper purchaseRequestDetailMapper;

    @Autowired
    private PurchasePlanMapper purchasePlanMapper;

    @Autowired
    private HttpServletResponse response;


    /**
     * 该公司所有意向的零件的实时库存
     *
     * @param saleIntentions
     * @param orgId
     * @return
     */
    private Map<String, BigDecimal>  getMaterialsQtyMap(List<SaleIntentionDO> saleIntentions, String orgId) {
        Map<String, BigDecimal> materialsNumMap = new HashMap<>();
        for (SaleIntentionDO saleIntentionDO : saleIntentions) {
            List<SaleIntentionDetailDO> details = saleIntentionDetailMapper.list(saleIntentionDO.getId());
            for (SaleIntentionDetailDO detail: details) {
                if (!materialsNumMap.containsKey(detail.getMaterialsNo())) {
                    materialsNumMap.put(detail.getMaterialsNo(), warehouseInventoryMapper.findEnableNum(detail.getMaterialsNo(), orgId, null));

                }
            }
        }
        return materialsNumMap;
    }

    /**
     *  净需求数量=  销售意向单中零件数量（如果为出库中状态，则需要减去已出库数量）
     *  剩余库存 = 计算可用库存 - 净需求数量
     *  计算可用 = 实时库存 + 在途数量
     *  实时库存 = 零件当前实际库存数量
     *  计划为执行 = 采购计划单中零件数量（功能未开发，没有数据），值先给0
     *  在途数量 = 采购单中零件数量，采购单（待审核，审核通过）
     * @param orgId
     */
    public void saveOrUpdatePurchasePlan(String orgId) {
        List<SaleIntentionDO> saleIntentions = saleIntentionMapper.listByOrgId(orgId);
        Map<String, BigDecimal> materialsNumMap = getMaterialsQtyMap(saleIntentions, orgId);
        Set<String> sameMaterialsNo = new HashSet<>();
        Map<String, BigDecimal> netDemandQty = new HashMap<>();
        for (int i = 0;i<saleIntentions.size();i++) {
            SaleIntentionDO saleIntentionDO = saleIntentions.get(i);
            List<SaleIntentionDetailDO> details = saleIntentionDetailMapper.list(saleIntentionDO.getId());
            for (SaleIntentionDetailDO detail: details) {
                if(detail.getAmountAfterAdjust().compareTo(detail.getInventoryOutAmount()) == 0){
                    continue;
                }
                boolean needUpdate = purchasePlanMapper.count(saleIntentionDO.getSaleNo(), detail.getMaterialsNo()) > 0;
                if(detail.getInventoryOutAmount() == null){
                    detail.setInventoryOutAmount(BigDecimal.ZERO);
                }
                // 计算净需求
                if (netDemandQty.containsKey(detail.getMaterialsNo())) {
                    netDemandQty.put(detail.getMaterialsNo(), netDemandQty.get(detail.getMaterialsNo()).add(detail.getAmountAfterAdjust().subtract(detail.getInventoryOutAmount())));
                } else {
                    netDemandQty.put(detail.getMaterialsNo(), detail.getAmountAfterAdjust().subtract(detail.getInventoryOutAmount()));
                }
                PurchasePlanDO planDO = new PurchasePlanDO();
                planDO.setBillNo(saleIntentionDO.getSaleNo());
                planDO.setOrgId(orgId);
                planDO.setMaterialsNo(detail.getMaterialsNo());
                planDO.setMaterialsDes(detail.getMaterialsDes());
                planDO.setDeliverTypeId(saleIntentionDO.getDeliverTypeId());
                planDO.setPurchaseType(saleIntentionDO.getPurchaseLevelName());
                planDO.setCreateBillDate(saleIntentionDO.getCreateDate());// 采购单生成时间
                // 在途数量
                BigDecimal passQty = getPurQtyByMaterialNoAndOrgId(detail.getMaterialsNo(), orgId);
                //计算可用
                BigDecimal calQty = materialsNumMap.get(detail.getMaterialsNo()).add(passQty);
                // 净需求数量
                planDO.setNeedAmount(detail.getAmountAfterAdjust().subtract(detail.getInventoryOutAmount()));
                // 剩余库存
                planDO.setSurplusAmount(calQty.subtract(netDemandQty.get(detail.getMaterialsNo())));
                //实时库存
                planDO.setRealAmount(materialsNumMap.get(detail.getMaterialsNo()));
                // 计算可用、采购计划未执行数量、在途数量只在列表中该零件第一次出现时候统计
                if (sameMaterialsNo.add(detail.getMaterialsNo())) {
                    // 计算可用
                    planDO.setUseableAmount(calQty);
                    // 采购计划未执行数量updateByBillNo
                    planDO.setPlanAmount(BigDecimal.ZERO);
                    // 在途数量
                    planDO.setPurchasedAmount(passQty);
                }

                planDO.setCreateDate(new Date());
                if (needUpdate) {
                    purchasePlanMapper.updateByBillNoAndMaterialsNo(planDO);
                } else {
                    purchasePlanMapper.insert(planDO);
                }


            }
        }
    }


    private BigDecimal getPurQtyByMaterialNoAndOrgId(String materialsNo, String orgId) {
        BigDecimal purQty = purchaseRequestDetailMapper.getPurQtyByMaterialNoAndOrgId(materialsNo, orgId);
        if (null == purQty) {
            return BigDecimal.ZERO;
        }
        return purQty;
    }

    /**
     * @Author: wangyong
     * @Description: 查询采购计划列表
     * @Date: 2018/5/18
     */
    public PageCommonVO list(SearchCommonVO<PurchasePlanVO> condition){
        PageCommonVO result = new PageCommonVO();
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<PurchasePlanDO> doList = purchasePlanMapper.list(condition.getFilters());
        List<PurchasePlanVO> voList = new ArrayList<>();
        for (PurchasePlanDO entity:doList) {
            PurchasePlanVO model=new PurchasePlanVO();
            BeanUtils.copyProperties(entity,model);
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    public void exportAll(PurchasePlanVO condition)throws Exception{
        Integer count = purchasePlanMapper.listCount(condition);
        List<PurchasePlanDO> dataList = new ArrayList<>();
        int times = count/500+1;
        for(int i=0; i<times; i++){
            PageHelperPlus.startPage(i + 1, 500);
            dataList.addAll(purchasePlanMapper.list(condition));
        }
        invokeExport(dataList);
    }

    private void invokeExport(List<PurchasePlanDO> doList)throws Exception{
        String title = "采购计划数据导出";
        String[] rowsName = new String[]{"序号","单号","订单时间","零件编码","零件名称",
                "采购级别", "净需求", "剩余库存", "计算可用库存","实时库存","采购计划未执行","在途数量","创建时间"};
        List<Object[]>  dataList = new ArrayList<Object[]>();
        Object[] objs;
        for (int i = 0; i < doList.size(); i++) {
            PurchasePlanDO exportDO = doList.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i+1;
            objs[1] = exportDO.getBillNo();
            objs[2] = DateUtil.formatDate(exportDO.getCreateBillDate());
            objs[3] = exportDO.getMaterialsNo();
            objs[4] = exportDO.getMaterialsDes();
            objs[5] = exportDO.getPurchaseType();
            objs[6] = exportDO.getNeedAmount();
            objs[7] = exportDO.getSurplusAmount();
            objs[8] = exportDO.getUseableAmount();
            objs[9] = exportDO.getRealAmount();
            objs[10] = exportDO.getPlanAmount();
            objs[11] = exportDO.getPurchasedAmount();
            objs[12] = DateUtil.formatDate(exportDO.getCreateDate());
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }
}
